/**
 * @class 太阳实体
 * @author DuskyHuang 圣子
*/
import { _decorator, Node, Camera, MeshRenderer, Vec3 } from 'cc';
import { ICelestial } from '../celestial';
import { CustomizedLOD } from '../entities/customized-lod';
import { VisitProxy, cosmos, solar, ui, visit } from 'proxies';
import { CelestialLabel } from '../ui/items/celestial-label';
import { setLabelStyle } from 'helpers';
import { attenuate } from 'algorithms';
import { SunPrecise } from '../stellar/sun-precise';
const { ccclass } = _decorator;

@ccclass('cocosmos.Sun')
export class Sun extends CustomizedLOD implements ICelestial {

    protected get LODValves(): num.pct[] { return SUN_LOD_VALVES };
    public readonly cat: into = 'star';
    public get config(): celestialConfig { return this._config; }

    public get nearest(): pow10 { return this._nearest + this._magnified; }
    public get suggest(): pow10 { return this.nearest + SUGGEST; }
    public get panorama(): pow10 { return this.nearest + 2; }
    public get refer(): Node { return this._precise.node ?? null; }

    public loadReference(precise: SunPrecise): void {
        this._precise = precise;
    }

    public get visible() { return this._visible; }
    public set visible(arg: boolean) {
        if (arg === this._visible) return;
        this.getComponentsInChildren(MeshRenderer).forEach(mesh => mesh.enabled = arg);
        this._visible = arg;
    }

    protected update(dt: time.sec): void {
        if (this._coronas) {
            this.faceToView(this._coronas);
            this._coronas.children.forEach((child, i) => {
                child.angle += dt * 10 * (0.5 - i);
            });
        }
    }

    public faceToView(child: Node): void {
        child.forward = Vec3.subtract(v3a, this.node.worldPosition, this._viewer.node.worldPosition);
    }


    public loadConfig(config: celestialConfig, viewer: Camera, base: pow10): void {
        this._config = config;
        this._viewer = viewer;
        const { diam } = config;
        this._real.set(diam, diam, diam);
        this.updateScale();
        this._nearest = Math.log10(diam) + base;
    }

    private _config: celestialConfig;
    private _visible: boolean = false;
    private _nearest: pow10 = 0;
    private _magnified: pow10 = 0;
    protected init(): void {
        this._coronas = this._lod0.getChildByName('Coronas');
        this._prominences = this._lod0.getChildByName('Prominences');
    }
    protected onLod0Initiated(): void { }
    protected onTick(): void {
        if (visit.inSolar && this.node.name === "Sun") {
            this._magnified = Math.log10(solar.getMagnified('star'));
        }
        this.syncNameLabel();
    }

    protected syncNameLabel(): void {
        if (this.node.activeInHierarchy && ui.showCelNames) {
            if (!this._label) {
                this._label = setLabelStyle(CelestialLabel.claim('solar', this.node.name), 'solar', 'sun');
                this._label.camera = this._viewer;
                this._label.target = this.node;
                this._label.key = `celestial@${this._config.name}`;
            }
            this._label.alpha = attenuate(cosmos.pow10, SUN_LABEL_ATT, false);
        } else this._freeLabel();
    }

    private _freeLabel(): void {
        if (this._label) {
            this._label.free();
            this._label = null;
        }
    }

    private _label: CelestialLabel = null;
    private _coronas: Node;
    private _prominences: Node;
    private _precise: SunPrecise = null;
}

const SUN_LABEL_ATT: attenuation = [-6.5, -5.5, -2.5, -1.5];
const { LensOffsets: { SUGGEST } } = VisitProxy;
const SUN_LOD_VALVES = [3, 0.9, 0.3];
const v3a = new Vec3;